
public class Menu {

    private static GameScreen gs;

    private int itemMaxLength, itemMaxWidth, itemFirstDraw, itemLastDraw, itemCurrent;
    private int posX, posY;
    public int itemsCount, itemHeight;
    private int     itemOffsetY, absolutLevelNumber;
    private short[] itemOffsetX;
    private byte state;

    private boolean titleVisible;

    private StringBuffer[] items;

/**************************************************************************************************/

    public Menu(GameScreen gs) {
        this.gs = gs;
    }

/**************************************************************************************************/

    public void creatMenu(byte[] states) {
        int i, count;

        itemMaxLength = 0;
        itemsCount = 0;
        for (i = 0; i < states.length; i++) {
            // Calculate max item count and max item length
            initItems(states[i], 0);
        }

        items = new StringBuffer[itemsCount];
        for (i = 0; i < itemsCount; i++) {
            items[i] = new StringBuffer(itemMaxLength);
        }
        itemOffsetX = new short[itemsCount];
        itemOffsetY = 2;
    }

/**************************************************************************************************/

    public void destroyMenu() {
        items = null;
        itemOffsetX = null;
        System.gc();
    }

/**************************************************************************************************/
/* Function inits menu items and variables                                                        */
/*    items         - text of menu items                                                          */
/*    itemsCount     - menu items count in the current menu                                       */
/*    itemMaxLength - max number of letters in the menu one items for the current menu            */
/*    itemMaxWidth  - max width of menu item                                                      */
/*    itemOffsetX[] - contains width each menu item                                               */
/**************************************************************************************************/
   
    private void initItems(int index, int mode) {
        StringBuffer tStr;
        int i, l, tInt, tIntRes;
        char ch;

        tStr = new StringBuffer(50);

        l = gs.strings[Constants.MENU_STR[index]].length() - 1;
        tIntRes = 0;
        for (i = 0; i <= l; i++) {
            ch = gs.strings[Constants.MENU_STR[index]].charAt(i);
            if (i == l) tStr.append(ch);
            if ((ch == '|') || (i == l)) {
                if (tStr.length() > itemMaxLength) itemMaxLength = tStr.length();
                if (mode == 1) {
                    items[tIntRes].append(tStr.toString());
                    tInt = gs.strGetWidth(tStr);
                    if (tInt > itemMaxWidth) itemMaxWidth = tInt;
                    itemOffsetX[tIntRes] = (short)tInt;
                }
                tIntRes++;
                gs.strClear(tStr);
            }
            else tStr.append(ch);
        }
        if (tIntRes > itemsCount) itemsCount = tIntRes;

        tStr = null;
        System.gc();
    }

/**************************************************************************************************/

    public int initMenu(byte state, int item)
    {
        return initMenu(state, 0, 0, gs.screenWidth, gs.screenHeight, true, item);
    }

/**************************************************************************************************/

    public int initMenu(byte state, int x, int y, int w, int h, boolean flag, int item) {
        int i, tInt;

        this.state = state;

        for (i = 0; i < items.length; i++) gs.strClear(items[i]);

        titleVisible = flag;
        itemsCount = 0;
        itemMaxLength = 0;
        itemMaxWidth = 0; 
      
        initItems(state, 1);

        itemMaxWidth += 10; 
        itemHeight = gs.fontHeight + 2;

        for (i = 0; i < itemsCount; i++) {
            itemOffsetX[i] = (short)((itemMaxWidth - itemOffsetX[i]) >> 1);
        }

        itemFirstDraw = 1;
        if (titleVisible) {
            itemLastDraw = ((h - (itemHeight + 2)) / itemHeight) - 1;
        }
        else {
            itemLastDraw = (h / itemHeight) - 1;
        }

        if (itemLastDraw > (itemsCount - 1)) itemLastDraw = itemsCount - 1;
      
        posX = x + ((w  - itemMaxWidth) >> 1);
      
        if (titleVisible) tInt = (itemLastDraw + 1) * itemHeight + (((itemLastDraw + 1) << 1) - 2);
        else tInt = (itemLastDraw) * itemHeight + (((itemLastDraw + 2) << 1) - 2);
        posY = y + ((h - tInt) >> 1);
        if (posY < 0) posY = 0;

        if (item < itemsCount) itemCurrent = item;
        else itemCurrent = itemsCount - 1;
      
        if ((state == Constants.GSS_MENU_JAR_LEVELS) || (state == Constants.GSS_MENU_RMS_LEVELS)) {
            absolutLevelNumber = gs.getAbsoluteLevelNumber(gs.groupCurrent, 0);
        }
        else absolutLevelNumber = 0;

        //#if !FULL_CANVAS
            if(!gs.getLabelCmd(gs.cmdLeft).equals(gs.strings[Constants.STR_SELECT])) {
                gs.removeAllCmds();
                gs.addCmd(Constants.KEY_SELECT, gs.strings[Constants.STR_SELECT]);
            }
        //#endif
        return state;
    }

/**************************************************************************************************/

    public int checkState(int code, boolean isKeyPressed) {
        int res = -1;
        if (isKeyPressed && ((code == Constants.KEYS[Constants.KEY_UP]) || (code == Constants.KEYS[Constants.KEY_NUM_2]))) {
            if(itemCurrent > 1) {
                itemCurrent--;
                if (itemCurrent < itemFirstDraw) {
                    itemFirstDraw --;
                    itemLastDraw --;
                }
            }
        }
        else if (isKeyPressed && ((code == Constants.KEYS[Constants.KEY_DOWN]) || (code == Constants.KEYS[Constants.KEY_NUM_8])))   {
            if (itemCurrent < (itemsCount - 1)) {
                itemCurrent++;
                if (itemCurrent > itemLastDraw) {
                    itemFirstDraw ++;
                    itemLastDraw ++;
                }
            }
        }
        else if (isKeyPressed && ((code == Constants.KEYS[Constants.KEY_FIRE]) || (code == Constants.KEYS[Constants.KEY_SELECT]) || (code == Constants.KEYS[Constants.KEY_NUM_5])) && !isMenuItemLocked(itemCurrent) && !isMenuItemPassed(itemCurrent)) {
            res = itemCurrent;
        }
        return res;
    }

/**************************************************************************************************/
   
    private boolean isMenuItemLocked(int index) {
        return (((state == Constants.GSS_MENU_JAR_LEVELS) || (state == Constants.GSS_MENU_RMS_LEVELS)) && ((gs.groupCurrent > gs.settings[Constants.SETTINGS_GROUP]) || ((gs.groupCurrent == gs.settings[Constants.SETTINGS_GROUP]) && ((index - 1) > gs.settings[Constants.SETTINGS_LEVEL]))) && (index < (itemsCount - 1))) || 
                ((state == Constants.GSS_MENU_GROUPS) && ((index - 1) > gs.settings[Constants.SETTINGS_GROUP]) && (index < (itemsCount - 1)));
    }

    private boolean isMenuItemPassed(int index) {
        return ((state == Constants.GSS_MENU_JAR_LEVELS) || (state == Constants.GSS_MENU_RMS_LEVELS)) && (0 < index) && (index <  (itemsCount - 1)) && ((absolutLevelNumber + index - 1) < gs.passedLevels.length) && (gs.passedLevels[absolutLevelNumber + index - 1] == 1);
    }

/**************************************************************************************************/

    public void drawMenu() {
        int i, j, tInt;
        boolean flag, flag1;

        if (titleVisible) {
            gs.fillBG(Constants.UI_MenuBorder, posX - 5, posY - 4, itemMaxWidth + 10, itemHeight + 2);
            gs.fillBG(Constants.UI_MenuHeaderColor, posX - 5, posY - 3, itemMaxWidth + 10, itemHeight);
            gs.drawString(items[0], posX + itemOffsetX[0], posY + itemOffsetY - 4);
            j = 1;
        }
        else j = 0;

        tInt = (itemLastDraw - itemFirstDraw);
        gs.fillBG(0x212121, posX - 1, posY + itemHeight - 1, itemMaxWidth + 2, (tInt + j) * itemHeight + ((tInt << 1) + 1) + 2);
        for (i = 0; i <= (itemLastDraw - itemFirstDraw); i++) {
            flag = isMenuItemLocked(itemFirstDraw + i);
            flag1 = isMenuItemPassed(itemFirstDraw + i);
            if ((itemFirstDraw + i) == itemCurrent) {
                if (flag) tInt = Constants.UI_ClosedMenuCursorColor;
                else if(flag1) tInt = Constants.UI_PassedMenuCursorColor;
                else tInt = Constants.UI_MenuCursorColor;
            }
            else {
                if (flag) tInt = Constants.UI_ClosedMenuBGColor;
                else if(flag1) tInt = Constants.UI_PassedMenuBGColor;
                else tInt = Constants.UI_MenuBGColor;
            }
            gs.fillBG(Constants.UI_MenuBorder, posX, posY + (i + j) * itemHeight + ((i << 1) + 1) - 1, itemMaxWidth, itemHeight + 1);
            gs.fillBG(tInt, posX, posY + (i + j) * itemHeight + ((i << 1) + 1), itemMaxWidth, itemHeight);
         
            gs.drawString(items[itemFirstDraw + i], posX, posY + (i + j) * itemHeight + ((i << 1) + 1) + itemOffsetY - 1, itemOffsetX[itemFirstDraw + i], itemMaxWidth);
        }
    }

/**************************************************************************************************/

}